/****************************************************
          File Name:14-3.h
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Sat Jan 10 18:01:44 2015
*****************************************************/

#ifndef QUEUE_H_
#define QUEUE_H_

template<typename T> class Queue
{
    private:
        struct Node { T item; struct Node *next; };
        enum {MAX=10};

        Node *front;
        Node *rear;
        int items;
        const int qsize;

        Queue(const Queue & q): qsize(0) {};
        Queue & operator=(const Queue & q) { return *this; }
    public:
        Queue(int qs = MAX);
        ~Queue();
        bool isempty() const;
        bool isfull() const;
        int count() const;
        bool enqueue(const T & item);
        bool dequeue(T & item);
};

template<typename T> Queue<T>::Queue(int qs) : qsize(qs)
{
    front = rear = nullptr;
    items = 0;
}

template<typename T> Queue<T>::~Queue()
{
    Node *tmp;
    while(front != nullptr)
    {
        tmp = front;
        front = front->next;
        delete [] tmp;
    }
}

template<typename T> bool Queue<T>::isempty() const
{
    return items == 0;
}

template<typename T> bool Queue<T>::isfull() const
{
    return items == qsize;
}

template<typename T> int Queue<T>::count() const
{
    return items;
}

template<typename T> bool Queue<T>::enqueue(const T & item)
{
    if(isfull())
        return false;

    Node *add = new Node;
    add->item = item;
    add->next = nullptr;

    items++;

    if(front == nullptr)
        front = add;
    else
        rear->next = add;

    rear = add;
    return true;
}

template<typename T> bool Queue<T>::dequeue(T & item)
{
    if(front == nullptr)
        return false;

    item = front->item;

    items--;

    Node *tmp = front;
    front = front->next;
    delete tmp;
    if(items == 0)
        rear = nullptr;
    return true;
}
#endif
